/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.dafe.springlink;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import org.openide.util.Lookup;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

/**
 *
 * @author dafe
 */
public final class NbSpringFactory {

    public static GenericApplicationContext createContext (String xmlConfigPath, Class clazz) {
        return createContext(clazz, new ClassPathResource(xmlConfigPath, clazz));
    }

    public static GenericApplicationContext createContext (Class clazz, Resource... resources) {
        GenericApplicationContext genCtx = new NbApplicationContext(Thread.currentThread().getContextClassLoader());
        XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(genCtx);

        for (Resource resource : resources) {
            xmlReader.loadBeanDefinitions(resource);
        }
        genCtx.refresh();

        return genCtx;
    }

    public static Lookup createLookup (GenericApplicationContext ctx) {
        return new SpringLookup(new InstanceContent(), ctx);
    }

    private static class SpringLookup extends AbstractLookup {

        private final InstanceContent ic;
        private final GenericApplicationContext ctx;

        public SpringLookup(InstanceContent ic, GenericApplicationContext ctx) {
            super(ic);
            this.ic = ic;
            this.ctx = ctx;
        }

        @Override
        protected void beforeLookup(Template<?> template) {
            super.beforeLookup(template);

            Class clazz = template.getType();
            Map beanMap = BeanFactoryUtils.beansOfTypeIncludingAncestors(
                    ctx, clazz);
            Collection instances = beanMap.values();
            for (Object springBean : instances) {
                ic.add(springBean);
            }
        }

    }

    public static class NbApplicationContext extends GenericApplicationContext {

        public NbApplicationContext(ClassLoader cl) {
            super();
            setClassLoader(cl);
        }

        @Override
        protected ResourcePatternResolver getResourcePatternResolver() {
            return new PathMatchingResourcePatternResolverEx(this);
        }

    };

    private static class PathMatchingResourcePatternResolverEx extends PathMatchingResourcePatternResolver {

        public PathMatchingResourcePatternResolverEx(ResourceLoader resourceLoader) {
            super(resourceLoader);
        }

        public PathMatchingResourcePatternResolverEx(ClassLoader classLoader) {
            super(classLoader);
        }

        public PathMatchingResourcePatternResolverEx() {
            super();
        }

        @Override
        protected boolean isJarResource(Resource resource) throws IOException {
            return super.isJarResource(resource) || "nbjcl".equals(resource.getURL().getProtocol());
        }
    }


}
